home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / ISSUE10 / COLLECTS / PIEGRAF.PAS next >
Encoding:
Pascal/Delphi Source File  |  1996-05-13  |  7.6 KB  |  263 lines

  1. unit piegraf;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  7.   Dialogs;
  8.  
  9. type
  10.  
  11.   TPieGraphic = class;
  12.  
  13.   TPieWedge = class(TCollectionItem)
  14.   private
  15.     FWedgeValue: Integer;    // Value which this wedge represents
  16.     FColor: TColor;          // Color to paint the wedge
  17.     FBrush: TBrush;          // Brush object to use in painting the wedge
  18.   public
  19.     constructor Create(Collection: TCollection); override;
  20.     destructor Destroy; override;
  21.     procedure Assign(Source: TPersistent); override;
  22.     procedure SetWedgeValue(Value: Integer);
  23.     procedure SetColor(Value: TColor);
  24.   published
  25.     { The published properties will be streamed automatically. }
  26.     property WedgeValue: Integer read FWedgeValue write SetWedgeValue;
  27.     property Color: TColor read FColor write SetColor;
  28.   end;
  29.  
  30.   TPiePieces = class(TCollection)
  31.   private
  32.     FPieGraphic: TPieGraphic; // Owner component of this property
  33.     FTotal: Integer;          // Total of all TPieWedge WedgeValues
  34.     function GetItem(Index: Integer): TPieWedge;
  35.     procedure SetItem(Index: Integer; Value: TPieWedge);
  36.   protected
  37.     procedure Update(Item: TCollectionItem); override;
  38.   public
  39.     constructor Create(PieGraphic: TPieGraphic);
  40.     function Add: TPieWedge;
  41.     procedure UpdatePiePieces;
  42.     function AddPiece(Value: Integer; wColor: TColor): TPieWedge;
  43.     property Items[Index: Integer]: TPieWedge read GetItem
  44.              write SetItem; default;
  45.     property Total: Integer read FTotal;
  46.   end;
  47.  
  48.   TPieGraphic = class(TGraphicControl)
  49.   private
  50.     FPiePieces: TPiePieces;  // Private storage for the TPiePieces property
  51.   protected
  52.     procedure SetPiePieces(Value: TPiePieces);
  53.   public
  54.     procedure Paint; override;
  55.     constructor Create(AOwner: TComponent); override;
  56.     destructor Destroy; override;
  57.     procedure AddPiece(Value: Integer; wColor: TColor);
  58.   published
  59.     property PiePieces: TPiePieces read FPiePieces write SetPiePieces;
  60.   end;
  61.  
  62. procedure Register;
  63.  
  64. implementation
  65. uses DsgnIntf, Piegrpe;
  66.  
  67. { TPieWedge }
  68.  
  69. constructor TPieWedge.Create(Collection: TCollection);
  70. { Calls inherited Create and passes collection which is then linked to this
  71.   TPieWedge instance. Also creates the FBrush instance. }
  72. begin
  73.   inherited Create(Collection);
  74.   FBrush := TBrush.Create;
  75. end;
  76.  
  77. destructor TPieWedge.Destroy;
  78. { Frees the FBrush instance before calling the inherited Destroy destructor. }
  79. begin
  80.   FBrush.Free;
  81.   inherited Destroy;
  82. end;
  83.  
  84. procedure TPieWedge.Assign(Source: TPersistent);
  85. { Copies the data from the TPieWedge parameter to this instances properties. }
  86. begin
  87.   if Source is TPieWedge then begin
  88.     { Assign property values via the property instead of directly to the
  89.       private storage so that the side-effects occur }
  90.     WedgeValue := TPieWedge(Source).WedgeValue;
  91.     Color := TPieWedge(Source).Color;
  92.     Exit;
  93.   end;
  94.   inherited Assign(Source);
  95. end;
  96.  
  97. procedure TPieWedge.SetWedgeValue(Value: Integer);
  98. { Copies data to the private storage. Also invokes Changed which causes the
  99.   linked TCollection to call it's Update method. See TPiePieces.Update. }
  100. begin
  101.   FWedgeValue := Value;
  102.   Changed(False);
  103. end;
  104.  
  105. procedure TPieWedge.SetColor(Value: TColor);
  106. { Copies data to the private storage and sets FBrush.Color as well. Also
  107.   invokes Changed which causes the linked TCollection to call it's
  108.   Update method. See TPiePieces.Update. }
  109. begin
  110.   FColor := Value;
  111.   FBrush.Color := Value;
  112.   Changed(False);
  113. end;
  114.  
  115. { TPiePieces }
  116.  
  117. constructor TPiePieces.Create(PieGraphic: TPieGraphic);
  118. { Calls the inherited Create constructor, passing the TCollectionItem type
  119.   so that this collection knows the type with which it will be used. Also
  120.   points it's private field FPieGraphic to the PieGraphic instance. }
  121. begin
  122.   inherited Create(TPieWedge);
  123.   FPieGraphic := PieGraphic;
  124. end;
  125.  
  126. function TPiePieces.GetItem(Index: Integer): TPieWedge;
  127. { Returns a reference to the Index'th TPieWedge in the collection }
  128. begin
  129.   Result := TPieWedge(inherited GetItem(Index));
  130. end;
  131.  
  132. procedure TPiePieces.SetItem(Index: Integer; Value: TPieWedge);
  133. { Sets the Index'th TPieWedge instance with the specified values. }
  134. begin
  135.   inherited SetItem(Index, Value);
  136. end;
  137.  
  138. function TPiePieces.Add: TPieWedge;
  139. { A wrapper around the TCollection.Add method. This Add method returns a
  140.   reference of the TPieWedge type whereas TCollectionAdd returns a reference
  141.   to a TCollectionItem type. This method just prevents the user of this
  142.   colletion from having to perform this step. }
  143. begin
  144.   Result := TPieWedge(inherited Add);
  145. end;
  146.  
  147. function TPiePieces.AddPiece(Value: Integer; wColor: TColor): TPieWedge;
  148. { Adds a new TPieWedge to the collection with the specified value and color. }
  149. begin
  150.   Result := Add;
  151.   Result.WedgeValue := Value;
  152.   Result.Color := wColor;
  153. end;
  154.  
  155. procedure TPiePieces.UpdatePiePieces;
  156. { Repaints FPieGraphic }
  157. begin
  158.   FPieGraphic.Refresh;
  159. end;
  160.  
  161. procedure TPiePieces.Update(Item: TCollectionItem);
  162. { TCollection.Update is called by TCollectionItems
  163.   whenever a change is made to any of the collection items. This is
  164.   initially an abstract method. It must be overriden to contain
  165.   whatever logic is necessary when a TCollectionItem has changed.  }
  166. var
  167.   i: integer;
  168. begin
  169.   { Since the user may have added or removed an item, recalculate the
  170.     FTotal value. }
  171.   FTotal := 0;
  172.   for i := 0 to Count - 1 do
  173.     FTotal := FTotal + Items[i].WedgeValue;
  174.   if Item <> nil then
  175.     UpdatePiePieces;
  176. end;
  177.  
  178. { TPieGraphic }
  179.  
  180. constructor TPieGraphic.Create(AOwner: TComponent);
  181. { Creates a TPiePieces instance and sets a defalt component size. }
  182. begin
  183.   inherited Create(AOwner);
  184.   FPiePieces := TPiePieces.Create(self);
  185.   Width := 200;
  186.   Height := 200;
  187. end;
  188.  
  189. destructor TPieGraphic.Destroy;
  190. { Frees the TPiePieces instance. }
  191. begin
  192.   FPiePieces.Free;
  193.   inherited Destroy;
  194. end;
  195.  
  196. procedure TPieGraphic.AddPiece(Value: Integer; wColor: TColor);
  197. { An interface function that adds a new pie wedge to the collection }
  198. begin
  199.   FPiePieces.AddPiece(Value, wColor);
  200.   Refresh;
  201. end;
  202.  
  203. procedure TPieGraphic.SetPiePieces(Value: TPiePieces);
  204. { Write access method for the PiePieces property }
  205. begin
  206.   FPiePieces.Assign(Value);
  207. end;
  208.  
  209. procedure TPieGraphic.Paint;
  210. { Iterates through each TPieWedge in FPiePieces' collection and paints it
  211.   using the specified color. }
  212. var
  213.   StartA, EndA: Integer;
  214.   midX, midY, stX, stY, endX, endY: Integer;
  215.   sX, sY, eX, eY: double;
  216.   i: integer;
  217. begin
  218.  
  219.   if FPiePieces.FTotal <> 0 then begin
  220.     StartA := 0;
  221.     for i := 0 to FPiePieces.Count - 1 do begin
  222.       if i = FPiePieces.Count - 1 then
  223.         EndA := 0
  224.       else begin
  225.         EndA := StartA + Trunc((Integer(FPiePieces.Items[i].FWedgeValue) /
  226.           FPiePieces.FTotal) * 360);
  227.         if EndA = StartA then EndA := StartA+1;
  228.       end;
  229.  
  230.       midX := Width div 2;
  231.       midY := Height div 2;
  232.  
  233.       sX := Cos((StartA / 180.0) * pi);
  234.       sY := Sin((StartA / 180.0) * pi);
  235.       eX := Cos((EndA / 180.0) * pi);
  236.       eY := Sin((EndA / 180.0) * pi);
  237.  
  238.       stX := Round(sX * 100);
  239.       stY := Round(sY * 100);
  240.       endX := Round(eX * 100);
  241.       endY := Round(eY * 100);
  242.  
  243.       with Canvas do
  244.       begin
  245.         { Copy the brush from the TPieWedge to this Canvas }
  246.         Brush := FPiePieces.Items[i].FBrush;
  247.         Pie(0,0, Width,Height, midX + stX, midY - stY,
  248.             midX + endX, midY - endY);
  249.       end;
  250.       StartA := EndA;
  251.     end;
  252.   end;
  253. end;
  254.  
  255. procedure Register;
  256. begin
  257.   RegisterComponents('Test', [TPieGraphic]);
  258.   RegisterPropertyEditor(TypeInfo(TPiePieces), TPieGraphic,
  259.                          'PiePieces', TPiePiecesProperty);
  260. end;
  261.  
  262. end.
  263.